// Package service
// Author liuzhiyong
// Date 2023/11/25
// Description 第一个go-kit测试程序 服务层
package service

import (
	"context"
	"errors"
	"gitee.com/liu_zy_developer/go-kit-demo/model/rpc_model"
	"github.com/go-kit/kit/endpoint"
	"math"
)

type AddService interface {
	Sum(ctx context.Context, a, b int) (int, error)
	Concat(ctx context.Context, a, b string) (string, error)
}

type addServiceImpl struct {
}

const maxLen = 10

var (
	// ErrTwoZeroes  Sum方法的业务规则不能对两个0求和
	ErrTwoZeroes = errors.New("can't sum two zeroes")

	// ErrIntOverflow Sum参数越界
	ErrIntOverflow = errors.New("integer overflow")

	// ErrTwoEmptyStrings Concat方法业务规则规定参数不能是两个空字符串.
	ErrTwoEmptyStrings = errors.New("can't concat two empty strings")

	// ErrMaxSizeExceeded Concat方法的参数超出范围
	ErrMaxSizeExceeded = errors.New("result exceeds maximum size")
)

// Sum 对两个数字求和，实现AddService。
func (s addServiceImpl) Sum(_ context.Context, a, b int) (int, error) {
	if a == 0 && b == 0 {
		return 0, ErrTwoZeroes
	}
	if (b > 0 && a > (math.MaxInt-b)) || (b < 0 && a < (math.MinInt-b)) {
		return 0, ErrIntOverflow
	}
	return a + b, nil
}

// Concat 连接两个字符串，实现AddService。
func (s addServiceImpl) Concat(_ context.Context, a, b string) (string, error) {
	if a == "" && b == "" {
		return "", ErrTwoEmptyStrings
	}
	if len(a)+len(b) > maxLen {
		return "", ErrMaxSizeExceeded
	}
	return a + b, nil
}

// NewAddService 创建一个AddService
func NewAddService() AddService {
	return &addServiceImpl{}
}

// ------------------------远程调用---------------------------------------

type withTrimMiddleware struct {
	next        AddService
	trimService endpoint.Endpoint // 通过它调用其他服务
}

func (w withTrimMiddleware) Sum(ctx context.Context, a, b int) (int, error) {
	return w.next.Sum(ctx, a, b) // 调原函数
}

func (w withTrimMiddleware) Concat(ctx context.Context, a, b string) (string, error) {
	// 先调用trim服务，去除字符串中可能存在的空格
	respA, err := w.trimService(ctx, rpc_model.TrimRequest{S: a}) // 请求trim服务处理a
	if err != nil {
		return "", err
	}
	respB, err := w.trimService(ctx, rpc_model.TrimRequest{S: b}) // 请求trim服务处理b
	if err != nil {
		return "", err
	}
	trimA := respA.(rpc_model.TrimResponse)
	trimB := respB.(rpc_model.TrimResponse)
	return w.next.Concat(ctx, trimA.S, trimB.S)
}

func NewServiceWithTrim(trimEndpoint endpoint.Endpoint, svc AddService) AddService {
	return &withTrimMiddleware{
		next:        svc,
		trimService: trimEndpoint,
	}
}
